package com.jiatuxueyuan.the4.remoteio;

import java.util.Date;

/**
 * 支持MQTT协议的传感器，不管它是本身就支持MQTT，还是普通传感器通过加配MQTT协议网关。
 *
 * 现场的传感器具备RS485接口并支持Modbus RTU协议，但是不具备联网能力，所以要为其配套一个支持MQTT协议的网关，这个网关负责：
 * <p>
 *     <ul>
 *         <li>1. 通过Modbus RTU协议读取传感器数据</li>
 *         <li>2. 通过MQTT协议，按照指定的周期上报数据</li>
 *     </ul>
 * </p>
 * <p>通过这个方式，就使得现场传感器的数据可以送到网络服务端进行存储、分析了。</p>
 */
public class MqttSensor {

    /**
     * 数据库主键
     */
    private int id;

    /**
     * 这个字段非常重要，全局唯一，每次MQTT上报的报文中必须要包含这个字段，否则没法区分是哪个传感器采集到的数据，MQTT报文中具体存放的采集到的数据
     * 以JSON的格式保存，比如下面的温度、湿度、JSON格式：
     *
     * {
     *     "sensorId" : "302045_2",     //前面是sensorId，后面是传感器类型，中间用下划线隔开，服务端解析的时候，就可以得到传感器类型，这样就知道有哪些指标，应该往哪张数据库表写入，同时还要在redis中保存一条这个传感器最新的一次采集的数据
     *     "temperature": 34.2,
     *     "humidity": 52,
     *     "pm25": 5.342,
     *     "pm10": 3.32,
     *     "h2s": 32.4,
     *     "o2": 321,
     *     "co": 45.23,
     *     "nh3": 0.771
     * }
     *
     * 所以上面JSON数据中的sensorId是非常重要的，如果没有这个值，相当于莫名其妙来了一笔采集数据。
     * <p>另外，服务端还需要对上传上来的数据做告警判断，判断当前值是否有问题，如果有问题则需要产生告警，告警不能误报、不能漏报、不能延误报警</p>
     *
     */
    private int sensorId;

    /**
     * 设备名称，方便现场管理
     */
    private String name;

    /**
     * 现场安装的位置，方便在客户端上显示
     */
    private String location;

    /**
     * 客户ID，这个传感器就是安装在这个客户现场的
     */
    private int customerId;

    /**
     * 客户名称
     */
    private String customer;

    /**
     * 安装在哪块区域，这个是区域ID，参考{@link Region}
     */
    private int regionId;

    /**
     * 区域名称，方便客户端展示
     */
    private String region;

    /**
     * 传感器类型，种类繁多，不同的传感器采集的指标也不一样，如何建模和保存呢？难道不同的传感器分别用不同的表来存放它采集的数据？
     * <p>
     *     <ul>
     *         <li>温湿度传感器</li>
     *         <li>光照传感器</li>
     *         <li>水浸传感器</li>
     *         <li>空气质量传感器（PM2.5、PM10）</li>
     *         <li>硫化氢传感器</li>
     *         <li>氧气传感器</li>
     *         <li>氨气传感器</li>
     *         <li>一氧化碳传感器</li>
     *         <li>土壤水份温度电导率传感器</li>
     *         <li>土壤PH值传感器</li>
     *         <li>液位传感器</li>
     *         <li>溶解氧传感器（溶解氧、饱和度、氧分压这三个测量指标）</li>
     *         <li>风向传感器</li>
     *         <li>风速传感器</li>
     *     </ul>
     * </p>
     *
     * <p>考虑这个思路：虽然传感器种类繁多，但是采集的指标加起来也不过几十个，顶多百八十个，建一个宽表，把所有数据全部放进去？但是这种
     * 情况的话，必然会有很多列是没有数据的，这个怎么整？填0进去？而且这种表的数据量过大，相当于所有客户的所有传感器数据都放在了一张表里面
     * </p>
     *
     * <p>第2个思路就是为每一种类型的传感器建一张表，表结构互不相同，但是也有几个字段是一样的，最终的格式是这样的：sensorId、timestamp、metric1、metric2、metric3.....metricN</p>
     * <p>收到上报的JSON数据后，怎么知道往哪一张表中存入数据呢？此时可以根据JSON中的sensorId就可以到DB中找到这个sensor的Type，也就知道对应的数据库表是哪一张了</p>
     * <p>在内存中维持一个Map映射： sensorType <---> t_metric_temperature_humidity，key是传感器类型，value是表名称 </p>
     */
    private int type;

    /**
     * 用来存放这个传感器数据的数据库表，这个是内部字段，不会呈现给用户看，不同类型的传感器数据放到不同的表中，这个字段是永远不能更改的！
     *
     * t_metric_temperature_humidity        温湿度传感器
     *
     * TODO：但是有的传感器只有一个测量指标，也要建一张表吗
     *
     */
    private String dataTableName;

    /**
     * mqtt服务端的IP地址，数据往这里送，我们可能会配置多台mqtt服务端节点
     */
    private String mqttServer;

    /**
     * mqtt服务的tcp端口
     */
    private int port;

    /**
     * 访问mqtt服务的用户名
     */
    private String username;

    /**
     * 访问mqtt访问的密码
     */
    private String password;

    /**
     * 这个字段非常重要，全局唯一，是MQTT协议中的客户端ID，不能重复，所以我们这里是自动生成的，现场实施的时候实施人员根据这个手动填写
     */
    private String mqttClientId;

    /**
     * 往哪个topic上面发布消息
     */
    private String topic;

    /**
     * 添加到数据库中的时间
     */
    private Date createDate;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public int getSensorId() {
        return sensorId;
    }

    public void setSensorId(int sensorId) {
        this.sensorId = sensorId;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getLocation() {
        return location;
    }

    public void setLocation(String location) {
        this.location = location;
    }

    public int getCustomerId() {
        return customerId;
    }

    public void setCustomerId(int customerId) {
        this.customerId = customerId;
    }

    public String getCustomer() {
        return customer;
    }

    public void setCustomer(String customer) {
        this.customer = customer;
    }

    public int getRegionId() {
        return regionId;
    }

    public void setRegionId(int regionId) {
        this.regionId = regionId;
    }

    public String getRegion() {
        return region;
    }

    public void setRegion(String region) {
        this.region = region;
    }

    public int getType() {
        return type;
    }

    public void setType(int type) {
        this.type = type;
    }

    public String getMqttServer() {
        return mqttServer;
    }

    public void setMqttServer(String mqttServer) {
        this.mqttServer = mqttServer;
    }

    public int getPort() {
        return port;
    }

    public void setPort(int port) {
        this.port = port;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getMqttClientId() {
        return mqttClientId;
    }

    public void setMqttClientId(String mqttClientId) {
        this.mqttClientId = mqttClientId;
    }

    public String getTopic() {
        return topic;
    }

    public void setTopic(String topic) {
        this.topic = topic;
    }

    public Date getCreateDate() {
        return createDate;
    }

    public void setCreateDate(Date createDate) {
        this.createDate = createDate;
    }
}
